<?php
/**
 * Class represents records from table coupon_batch
 * * * * * * * {autogenerated}
 * @property int $batch_id
 * @property string $comment
 * @property string $discount_type enum('percent','number')
 * @property double $discount
 * @property date $begin_date
 * @property date $expire_date
 * @property int $is_disabled
 * @property int $is_recurring
 * @property string $product_ids
 * @property int $use_count
 * @property int $user_use_count
 * @property int $user_id
 * @see Am_Table
 */
class CouponBatch extends Am_Record
{
    function delete()
    {
        $this->deleteFromRelatedTable('?_coupon');
        parent::delete();
    }

    function generateCoupons($count, $minLen, $maxLen, $prefix = null)
    {
        $table = $this->getDi()->couponTable;
        for ($i=0; $i<$count; $i++){
            $coupon = $this->getDi()->couponRecord;
            $coupon->code = $table->generateCouponCode($minLen, $maxLen, $prefix);
            $coupon->batch_id = $this->pk();
            $coupon->insert();
        }
    }

    /**
     * Retrieve array of product ids coupon can be applied for
     *
     * @return array|null null in case of there is not any restriction
     */
    function getApplicableProductIds()
    {
        return $this->_getProductIds('product_ids');
    }

    /**
     * Retrieve array of product ids coupon can not be applied for
     *
     * @return array|null null in case of there is not any restriction
     */
    function getNotApplicableProductIds()
    {
        return $this->_getProductIds('not_product_ids');
    }

    protected function _getProductIds($token)
    {
        //return null in case this field is empty
        if (!$this->$token) return null;

        $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts();
        $res = array_filter(explode(',', $this->$token));
        foreach ($res as $k => $g) {
            if (preg_match('/BP-(\d*)/', $g, $match)) {
                unset($res[$k]);
            }
            if (preg_match('/CATEGORY-(\d*)/', $g, $match)) {
                unset($res[$k]);
                $catId = $match[1];
                foreach ($catProducts[$catId] as $prId) {
                    $res[] = $prId;
                }
            }
        }
        return $res;
    }

    function getOnlyApplicableProductIds()
    {
        return $this->_getOnlyProductIds('product_ids');
    }

    function getOnlyNotApplicableProductIds()
    {
        return $this->_getOnlyProductIds('not_product_ids');
    }

    protected function _getOnlyProductIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (!preg_match('/CATEGORY-(\d*)/', $g, $match)) {
                $result[] = $g;
            }
        }
        return $result;
    }

    function getOnlyApplicableCategoryIds()
    {
        return $this->_getOnlyCategoryIds('product_ids');
    }

    function getOnlyNotApplicableCategoryIds()
    {
        return $this->_getOnlyCategoryIds('not_product_ids');
    }

    protected function _getOnlyCategoryIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/CATEGORY-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
        }
        return $result;
    }

    function getApplicableBpIds()
    {
        return $this->_getBpIds('product_ids');
    }

    function getNotApplicableBpIds()
    {
        return $this->_getBpIds('not_product_ids');
    }

    protected function _getBpIds($token)
    {
        $res = array_filter(explode(',', $this->$token ?? ''));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/BP-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
        }
        return $result;
    }

    function getRequireProduct()
    {
        return array_unique(array_filter($this->parseRequirementsGroup($this->require_product)));
    }

    function getPreventIfProduct()
    {
        return array_unique(array_filter($this->parseRequirementsGroup($this->prevent_if_product)));
    }

    /**
     * @param string $req
     * @return array
     */
    protected function parseRequirementsGroup($req)
    {
        $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts();
        $res = array_filter(explode(',',$req ?? ''));
        foreach ($res as $k => $g) {
            if (preg_match('/CATEGORY-(\w*)-(\d*)/', $g, $match)) {
                unset($res[$k]);
                $status = $match[1];
                $catId = $match[2];
                foreach ($catProducts[$catId] as $prId) {
                    $res[] = sprintf('%s-%d', $status, $prId);
                }
            }
        }
        return $res;
    }
}

class CouponBatchTable extends Am_Table
{
    protected $_key = 'batch_id';
    protected $_table = '?_coupon_batch';
    protected $_recordClass = 'CouponBatch';

    function deleteByUserId($user_id)
    {
        if (!$user_id)
            throw new Am_Exception_InternalError("user_id is empty in " . __METHOD__);
        $list = $this->_db->selectCol("SELECT batch_id FROM ?_coupon_batch WHERE user_id=?d", $user_id);
        if ($list)
            $this->_db->query("DELETE FROM ?_coupon_batch, ?_coupon WHERE batch_id IN (?a)", $list);
    }

    function getOptions($onlyEnabled = true)
    {
        return array_map(['Am_Html', 'escape'], $this->_db->selectCol("SELECT batch_id as ARRAY_KEY,
            CONCAT('#', batch_id, ' ', IF(comment<>'', comment, CONCAT(discount, IF(discount_type='percent', '%', '$'), IF(begin_date, CONCAT(' (', begin_date, ' - ', expire_date, ')'), ''))))
            FROM ?_coupon_batch
            {WHERE is_disabled = ?}",
            $onlyEnabled ? 0 : DBSIMPLE_SKIP));
    }
}